Imports Clo = Enhancements.Core.Logging
Imports Fun = Enhancements.Basic.Expressions.Functions
Imports Gen = System.Collections.Generic
Imports Glo = System.Globalization
Imports Lev = Enhancements.Basic.Expressions.Levels
Imports Ope = Enhancements.Basic.Expressions.Operators
Imports Ref = System.Reflection
Imports Sys = System
Imports Val = Enhancements.Basic.Expressions.Values

Namespace Enhancements.Basic.Expressions
    Partial Class Compiler
        <Serializable()> _
        Private NotInheritable Class __ExpressionLexicalAnalysis

            Private Sub New()
            End Sub

            ''' <exception cref="IsNullException"> </exception>
            ''' <exception cref="CompilerExpressionIsEmptyException"> </exception>
            ''' <exception cref="CompilerExpressionStringsDelimitersCountIsValidNotException"></exception>
            ''' <exception cref="CompilerExpressionStringsAreValidNotException"></exception>
            ''' <exception cref="CompilerExpressionDateTimesDelimitersCountIsValidNotException"> </exception>
            ''' <exception cref="CompilerExpressionDateTimesAreValidNotException"> </exception>
            ''' <exception cref="CompilerExpressionLevelsDelimitersCountAreEqualNotException"> </exception>
            ''' <exception cref="CompilerExpressionLevelsDelimitersAreValidNotException"> </exception>
            ''' <exception cref="CompilerExpressionHasUndeterminedTokensException"> </exception>
            ''' <exception cref="CompilerExpressionHasWhiteSpaceTokensOnlyException"> </exception>
            Friend Shared Function AssertAndParse(ByVal _compiler As Compiler, ByVal _expression As System.String) As Gen.List(Of Token)
                _compiler.IsNullNot("_compiler", True)
                _expression.IsNullNot("_expression", True)

                Dim _tokenUndetermined As Undetermined = Nothing
                Try
                    _tokenUndetermined = New Undetermined(_expression, 0, _expression.Length - 1)
                Catch _exception As IsEmptyException
                    CompilerExpressionIsEmptyException.___Throw(_expression)
                End Try
                Dim _returnValue As Gen.List(Of Token) = New Gen.List(Of Token)()
                _returnValue.AddRange(Val.String.___ParseAll(_tokenUndetermined))
                Val.DateTime.___ParseAll(_returnValue)
                Variable.___ParseAll(_returnValue)
                WhiteSpace.___ParseAll(_returnValue)
                Fun.FunctionParametersSeparator.___ParseAll(_returnValue)
                Lev.DelimiterBegin.___ParseAll(_returnValue)
                Lev.DelimiterEnd.___ParseAll(_returnValue)
                Lev.Delimiter.___Assert(_returnValue)
                AssertAndParseFunctionsAndOperatorsAndBooleanValues(_compiler, _returnValue)
                Val.Decimal.___ParseAll(_returnValue)
                Val.Integer.___ParseAll(_returnValue)
                Dim _tokensUndetermined() As Undetermined = Undetermined.___PutInArray(_returnValue)
                If _tokensUndetermined.Length.IsInRangeNot("_tokensUndetermined.Length", 0, 0, False) Then
                    CompilerExpressionHasUndeterminedTokensException.___Throw(_expression, _tokensUndetermined)
                End If
                WhiteSpace.___RemoveAll(_returnValue)
                If _returnValue.Count.IsInRange("_returnValue.Count", 0, 0, False) Then
                    CompilerExpressionHasWhiteSpaceTokensOnlyException.___Throw(_expression)
                End If

                Return _returnValue
            End Function

            ''' <exception cref="IsNullException"> </exception>
            ''' <exception cref="IsListFilledNotException"> </exception>
            Private Shared Function AssertAndParseFunctionsAndOperatorsAndBooleanValues(ByVal _compiler As Compiler, ByRef _tokens As Gen.List(Of Token)) As Sys.Int32
                _compiler.IsNullNot("_compiler", True)
                _tokens.IsListFilled("_tokens", True)

                Dim _returnValue As Sys.Int32 = 0
                Dim _tokensNew As Gen.List(Of Token) = New Gen.List(Of Token)()
                For _counter1 As Sys.Int32 = 0 To _tokens.Count - 1
                    If _tokens(_counter1).IsOfType("_tokens(_counter1)", GetType(Undetermined), False) Then
                        Dim _tokensToken As Undetermined = CType(_tokens(_counter1), Undetermined)
                        For _counter2 As Sys.Int32 = 0 To _tokensToken.ExpressionPart.Length - 1
                            Dim _tokenWasFound As System.Boolean = False
                            For Each _item As KeyValuePair(Of System.String, ___FunctionsAndOperatorsAndBooleanValuesItem) In _compiler.___FunctionsAndOperatorsAndBooleanValuesSortedGet()
                                Select Case _item.Value.Type
                                    Case ___FunctionsAndOperatorsAndBooleanValuesItemType.Function
                                        Dim _itemData As Fun.Function = CType(_item.Value.Data, Fun.Function)
                                        Dim _functionName As Fun.FunctionName = Nothing
                                        If Fun.FunctionName.___TryParse(_tokensToken.Expression, _tokensToken.ExpressionBeginIndex + _counter2, _itemData, _functionName) Then
                                            _tokensNew.Add(_functionName)
                                            _counter2 += _functionName.ExpressionPart.Length - 1
                                            _tokenWasFound = True
                                            _returnValue += 1
                                            Exit For
                                        End If
                                    Case ___FunctionsAndOperatorsAndBooleanValuesItemType.Operator
                                        Dim _itemData As Sys.Type = CType(_item.Value.Data, Sys.Type)
                                        Dim _operator As Ope.Operator = Nothing
                                        If Ope.Operator.___TryParse(_tokensToken.Expression, _tokensToken.ExpressionBeginIndex + _counter2, _itemData, _operator) Then
                                            _tokensNew.Add(_operator)
                                            _counter2 += _operator.ExpressionPart.Length - 1
                                            _tokenWasFound = True
                                            _returnValue += 1
                                            Exit For
                                        End If
                                    Case ___FunctionsAndOperatorsAndBooleanValuesItemType.BooleanFalseValue
                                        Dim _boolean As Val.Boolean = Nothing
                                        If Val.Boolean.TryParse(_tokensToken.Expression, _tokensToken.ExpressionBeginIndex + _counter2, _boolean) Then
                                            If CType(_boolean.Value, System.Boolean) = False Then
                                                _tokensNew.Add(_boolean)
                                                _counter2 += _boolean.ExpressionPart.Length - 1
                                                _tokenWasFound = True
                                                _returnValue += 1
                                                Exit For
                                            End If
                                        End If
                                    Case ___FunctionsAndOperatorsAndBooleanValuesItemType.BooleanTrueValue
                                        Dim _boolean As Val.Boolean = Nothing
                                        If Val.Boolean.TryParse(_tokensToken.Expression, _tokensToken.ExpressionBeginIndex + _counter2, _boolean) Then
                                            If CType(_boolean.Value, System.Boolean) = True Then
                                                _tokensNew.Add(_boolean)
                                                _counter2 += _boolean.ExpressionPart.Length - 1
                                                _tokenWasFound = True
                                                _returnValue += 1
                                                Exit For
                                            End If
                                        End If
                                End Select
                            Next _item
                            If Not _tokenWasFound Then
                                Undetermined.___AppendNewToEndOrReplaceLastWithNew(_tokensNew, _tokensToken.Expression, _tokensToken.ExpressionBeginIndex + _counter2, _tokensToken.ExpressionBeginIndex + _counter2)
                            End If
                        Next _counter2
                    Else
                        _tokensNew.Add(_tokens(_counter1))
                    End If
                Next _counter1
                _tokens = _tokensNew

                Return _returnValue
            End Function

        End Class
    End Class
End Namespace
